[IA64] IO ports for driver domains.
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Thu, 27 Jul 2006 16:00:00 +0000 (10:00 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Thu, 27 Jul 2006 16:00:00 +0000 (10:00 -0600)
Map/unmap IO ports.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
xen/arch/ia64/xen/dom0_ops.c
xen/arch/ia64/xen/dom_fw.c
xen/arch/ia64/xen/mm.c
xen/include/asm-ia64/domain.h
xen/include/asm-ia64/iocap.h

index 28f06d90d1e6d16154899ddcc863b92a7884846e..3561668b58a91093b52a602f3c820aebdf1f8192 100644 (file)
@@ -285,6 +285,7 @@ long arch_do_dom0_op(dom0_op_t *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
         struct domain *d;
         unsigned int fp = op->u.ioport_permission.first_port;
         unsigned int np = op->u.ioport_permission.nr_ports;
+        unsigned int lp = fp + np - 1;
 
         ret = -ESRCH;
         d = find_domain_by_id(op->u.ioport_permission.domain);
@@ -295,9 +296,9 @@ long arch_do_dom0_op(dom0_op_t *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
             ret = 0;
         else {
             if (op->u.ioport_permission.allow_access)
-                ret = ioports_permit_access(d, fp, fp + np - 1);
+                ret = ioports_permit_access(d, fp, lp);
             else
-                ret = ioports_deny_access(d, fp, fp + np - 1);
+                ret = ioports_deny_access(d, fp, lp);
         }
 
         put_domain(d);
index ea9c06fd1d6700d4a2826bd5845ad341e48767c7..a3f699646b3420b5a67ebf2315f4aac03de3d7f6 100644 (file)
@@ -855,15 +855,17 @@ dom_fw_init (struct domain *d, struct ia64_boot_param *bp, char *fw_mem, int fw_
        } else {
 #ifndef CONFIG_XEN_IA64_DOM0_VP
                /* Dom0 maps legacy mmio in first MB.  */
-               MAKE_MD(EFI_LOADER_DATA,EFI_MEMORY_WB,0*MB,1*MB, 1);
-               MAKE_MD(EFI_CONVENTIONAL_MEMORY,EFI_MEMORY_WB,HYPERCALL_END,maxmem, 1);
+               MAKE_MD(EFI_LOADER_DATA, EFI_MEMORY_WB, 0*MB, 1*MB, 1);
+               MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB,
+                       HYPERCALL_END, maxmem, 1);
 #endif
-               /* hypercall patches live here, masquerade as reserved PAL memory */
-               MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME,HYPERCALL_START,HYPERCALL_END, 1);
-               /* Create a dummy entry for IO ports, so that IO accesses are
-                  trapped by Xen.  */
-               MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE,EFI_MEMORY_UC,
-                       0x00000ffffc000000, 0x00000fffffffffff, 1);
+               /* hypercall patches live here, masquerade as reserved
+                  PAL memory */
+               MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME,
+                       HYPERCALL_START, HYPERCALL_END, 1);
+               /* Create an entry for IO ports.  */
+               MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC,
+                       IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE, 1);
                MAKE_MD(EFI_RESERVED_TYPE,0,0,0,0);
        }
 
index e541a1660d24951e4ecae6d62d882e0b37329bfc..5a24f06a8fac89b81e215a992ee05c3b930fcb61 100644 (file)
@@ -180,6 +180,8 @@ static void domain_page_flush(struct domain* d, unsigned long mpaddr,
                               unsigned long old_mfn, unsigned long new_mfn);
 #endif
 
+extern unsigned long ia64_iobase;
+
 static struct domain *dom_xen, *dom_io;
 
 // followings are stolen from arch_init_memory() @ xen/arch/x86/mm.c
@@ -894,6 +896,60 @@ assign_domain_page(struct domain *d,
     __assign_domain_page(d, mpaddr, physaddr, ASSIGN_writable);
 }
 
+int
+ioports_permit_access(struct domain *d, unsigned long fp, unsigned long lp)
+{
+    int ret;
+    unsigned long off;
+    unsigned long fp_offset;
+    unsigned long lp_offset;
+
+    ret = rangeset_add_range(d->arch.ioport_caps, fp, lp);
+    if (ret != 0)
+        return ret;
+
+    fp_offset = IO_SPACE_SPARSE_ENCODING(fp) & ~PAGE_MASK;
+    lp_offset = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp));
+
+    for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE)
+        __assign_domain_page(d, IO_PORTS_PADDR + off,
+                             ia64_iobase + off, ASSIGN_nocache);
+
+    return 0;
+}
+
+int
+ioports_deny_access(struct domain *d, unsigned long fp, unsigned long lp)
+{
+    int ret;
+    struct mm_struct *mm = &d->arch.mm;
+    unsigned long off;
+    unsigned long fp_offset;
+    unsigned long lp_offset;
+
+    ret = rangeset_remove_range(d->arch.ioport_caps, fp, lp);
+    if (ret != 0)
+        return ret;
+
+    fp_offset = IO_SPACE_SPARSE_ENCODING(fp) & ~PAGE_MASK;
+    lp_offset = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp));
+
+    for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE) {
+        unsigned long mpaddr = IO_PORTS_PADDR + off;
+        volatile pte_t *pte;
+        pte_t old_pte;
+
+        pte = lookup_noalloc_domain_pte_none(d, mpaddr);
+        BUG_ON(pte == NULL);
+        BUG_ON(pte_none(*pte));
+
+        // clear pte
+        old_pte = ptep_get_and_clear(mm, mpaddr, pte);
+    }
+    domain_flush_vtlb_all();
+    return 0;
+}
+
 #ifdef CONFIG_XEN_IA64_DOM0_VP
 static void
 assign_domain_same_page(struct domain *d,
index 1d1bbf51d8680ba8510e4a97018809c6e13c54d2..9546adbc62b5663efe6f0927bfed50c32063b7ac 100644 (file)
@@ -196,6 +196,10 @@ struct arch_vcpu {
 #include <asm/uaccess.h> /* for KERNEL_DS */
 #include <asm/pgtable.h>
 
+/* Guest physical address of IO ports space.  */
+#define IO_PORTS_PADDR          0x00000ffffc000000UL
+#define IO_PORTS_SIZE           0x0000000004000000UL
+
 #endif /* __ASM_DOMAIN_H__ */
 
 /*
index 8ee571bf6543f5b8799b316bdcea137477749d26..0a0e0215e2f67b22c5433ca798bd65b65df74361 100644 (file)
@@ -7,10 +7,11 @@
 #ifndef __IA64_IOCAP_H__
 #define __IA64_IOCAP_H__
 
-#define ioports_permit_access(d, s, e)                  \
-    rangeset_add_range((d)->arch.ioport_caps, s, e)
-#define ioports_deny_access(d, s, e)                    \
-    rangeset_remove_range((d)->arch.ioport_caps, s, e)
+extern int ioports_permit_access(struct domain *d,
+                                 unsigned long s, unsigned long e);
+extern int ioports_deny_access(struct domain *d,
+                               unsigned long s, unsigned long e);
+
 #define ioports_access_permitted(d, s, e)               \
     rangeset_contains_range((d)->arch.ioport_caps, s, e)